package com.simple.relaxed.local;

import com.simple.relaxed.anno.*;
import com.simple.relaxed.anno.impl.AsyncTaskImpl;
import com.simple.relaxed.anno.impl.InjectImpl;
import lombok.Getter;
import ohos.agp.components.Component;
import ohos.agp.components.LayoutScatter;
import ohos.app.Context;
import ohos.app.dispatcher.TaskDispatcher;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public abstract class LocalLayout {

    /**
     * UI任务调度器
     */
    protected TaskDispatcher uiTaskDispatcher;

    /**
     * LocalLayout的类对象，当然不局限于LayoutLayout，它也可以是LocalLayout的类对象
     */
    private Class<? extends LocalLayout> aClass;

    /**
     * 使用它的上下文对象，通常是使用它的AbilitySlice对象
     */
    protected Context context;

    /**
     * 此LocalLayout的主布局映射对象，它将作为Java程序中，运行时视图对象，管理他的所有子类视图
     */
    @Getter
    protected Component component;

    public LocalLayout(Context context) {
        this.context = context;
        this.aClass = this.getClass();
        // 自动注入Inject
        InjectImpl.inject(this);
        // 初始化视图
        initLayout();
        // 初始化控件
        this.initComponent();
        // 初始化控件值
        this.initComponentValue();
        // 初始化控件的点击事件
        this.initComponentClick();
        // 初始化控件的长按事件
        this.initComponentLongClick();
        // 扫描异步任务
        AsyncTaskImpl.asyncTask(this);
    }

    public abstract void load();

    private void initLayout() {
        Layout layout = aClass.getDeclaredAnnotation(Layout.class);
        if (layout == null) {
            throw new IllegalArgumentException("缺少注解：".concat(Layout.class.getName()));
        }
        component = LayoutScatter.getInstance(context).parse(layout.layoutId(), null, false);
    }

    /**
     * 此方法会寻找当前Slice中，携带了InitComponent注解的Filed，并且将指定Id的Component对象，注入到Filed中
     */
    private void initComponent() {
        Field[] fields = aClass.getDeclaredFields();
        for (Field field : fields) {
            InitComponent component = field.getDeclaredAnnotation(InitComponent.class);
            if (component == null) {
                continue;
            }
            int componentId = component.componentId();
            Component c = this.component.findComponentById(componentId);
            field.setAccessible(true);
            try {
                field.set(this, c);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 自动触发被标记了InitValue注解得方法，主要用于做一些值初始化操作
     */
    private void initComponentValue() {
        Method[] methods = aClass.getDeclaredMethods();
        for (Method method : methods) {
            InitValue initValue = method.getDeclaredAnnotation(InitValue.class);
            if (initValue == null) {
                continue;
            }
            method.setAccessible(true);
            try {
                method.invoke(this);
            } catch (IllegalAccessException | InvocationTargetException e) {
                e.printStackTrace();
            }
            break;
        }
    }

    /**
     * 自动注入当前Slice中被标记了OnClick注解的方法，为指定Component的点击事件
     */
    private void initComponentClick() {
        Method[] methods = aClass.getDeclaredMethods();
        for (Method method : methods) {
            OnClick onClick = method.getDeclaredAnnotation(OnClick.class);
            if (onClick == null) {
                continue;
            }
            int componentId = onClick.componentId();
            Component component = this.component.findComponentById(componentId);
            component.setClickedListener((c) -> {
                method.setAccessible(true);
                int parameterCount = method.getParameterCount();
                try {
                    if (parameterCount == 0) {
                        method.invoke(this);
                    } else {
                        method.invoke(this, c);
                    }
                } catch (IllegalAccessException | InvocationTargetException e) {
                    e.printStackTrace();
                }
            });
        }
    }

    /**
     * 自动注入当前Slice中被标记了OnLongClick注解的方法，为指定Component的长按事件
     */
    private void initComponentLongClick() {
        Method[] methods = aClass.getDeclaredMethods();
        for (Method method : methods) {
            OnLongClick longClick = method.getDeclaredAnnotation(OnLongClick.class);
            if (longClick == null) {
                continue;
            }
            int componentId = longClick.componentId();
            Component c = component.findComponentById(componentId);
            c.setLongClickedListener((component) -> {
                method.setAccessible(true);
                int count = method.getParameterCount();
                try {
                    if (count == 0) {
                        method.invoke(this);
                    } else {
                        method.invoke(this, component);
                    }
                } catch (IllegalAccessException | InvocationTargetException e) {
                    e.printStackTrace();
                }
            });
        }
    }
}
